package org.huangjiahui.rpc.transport.netty.server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.huangjiahui.rpc.entity.RpcRequest;
import org.huangjiahui.rpc.entity.RpcResponse;
import org.huangjiahui.rpc.factory.SingletonFactory;
import org.huangjiahui.rpc.handler.RequestHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Netty中处理RpcRequest的Handler
 * @author huangjiahui
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);
    private final RequestHandler requestHandler;

    public NettyServerHandler(){this.requestHandler = SingletonFactory.getInstance(RequestHandler.class); }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest) throws Exception {
        try {
            if(rpcRequest.getHeartBeat()){
                logger.info("接受到客户端心跳包...");
                return;
            }
            logger.info("服务器接收到请求:{}",rpcRequest);
            Object result = requestHandler.handle(rpcRequest);
            if(channelHandlerContext.channel().isActive() && channelHandlerContext.channel().isWritable()){
                channelHandlerContext.writeAndFlush(RpcResponse.success(result,rpcRequest.getRequestId()));
            }else{
                logger.error("通道不可写");
            }
        }finally {
            ReferenceCountUtil.release(rpcRequest);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable cause) throws Exception{
        logger.error("处理过程调用时有错误发生:");
        cause.printStackTrace();
        channelHandlerContext.close();
    }

    @Override
    public  void userEventTriggered(ChannelHandlerContext channelHandlerContext, Object evt) throws Exception{
        if(evt instanceof IdleStateEvent){
            IdleState state = ((IdleStateEvent) evt).state();
            if(state == IdleState.READER_IDLE){
                logger.info("长时间未收到心跳包，断开连接");
                channelHandlerContext.close();
            }
        }else{
            super.userEventTriggered(channelHandlerContext,evt);
        }
    }

}
